// -*- coding: utf-8 -*-

#ifndef HYBRID_UTIL_H
#define HYBRID_UTIL_H

#include <iostream>
#include <fstream>
#include <iomanip>
#include "hybrid_var.h"

NAMESPACE_ELISA

typedef std::pair<VNIntPtr, VNIntPtr> VNIntPair;

namespace vn 
{

static const VNInterval Unit(0.0, 1.0);

inline const VNInterval hull(const VNInterval& x, const VNInterval& y)
{
	// FIXME: gaolのメソッド呼び出し
	if (x.is_empty()) {
		return y;
	} else {
	if (y.is_empty()) {
			return x;
		} else {
			return VNInterval(std::min<double>(v_bias::inf(x), v_bias::inf(y)), 
							  std::max<double>(v_bias::sup(x), v_bias::sup(y)));
		}
	}
}

inline const VNIntPair split(const VNInterval& x)
{
	double mid = v_bias::midpoint(x);
	return VNIntPair(VNIntPtr(new VNInterval(v_bias::inf(x), mid)), VNIntPtr(new VNInterval(mid, v_bias::sup(x))));
}

inline bool isPossiblyLessThan(const VNInterval& x, const VNInterval& y)
{
	// FIXME: gaolのメソッド呼び出し
	return x.possibly_leq(y);
}

inline bool isCertainlyLessThan(const VNInterval& x, const VNInterval& y)
{
	// FIXME: gaolのメソッド呼び出し
	return x.certainly_leq(y);
}

inline void dumpIntVec(std::ostream& out, VNIntVec iv)
{
	out << std::setprecision(16);
	out << '(' << std::endl;
	for (int i(0); i < iv.size(); i++) {
		out << i << ": " << iv[i] << std::endl;
	}
	out << ')' << std::endl;
}

}


//std::ofstream odeOut("ode_dump.dat",  ios::out);
extern std::ofstream odeOut;
extern std::ofstream nrwOut;

inline void startDumpTightEncl()
{
	//odeOut << '[' << endl;
}

inline void endDumpTightEncl()
{
	//odeOut << "{}"; // ダミーオブジェクト
	//odeOut << endl << ']';
}

inline void dumpPipe(std::ostream& out,
					 ContConstraint& constr, 
					 const VNInterval& time, const VNIntVec& iv)
{
	// 時間
	out << "{" << std::endl;
	out << "  \"type\":\t\"tight\"," << std::endl;
	out << "  \"time\":\t";
	out << '[' << v_bias::inf(time) << ',' << v_bias::sup(time) << ']';

	// 各軸
	const ContVarVec & cvv = constr.rep()->getContVars();
	for (int i(0); i < cvv.size(); ++i) {
		out << ',' << std::endl;

		ContVarImpl *cv = dynamic_cast<ContVarImpl *>(cvv[i]->getImplementation().get());

		// 変数名
		out << "  \"" << cv->getSymbolicRep()->getName() << "\":\t";
		// 値
		//out << iv[i];
		out << '[' << v_bias::inf(iv[i]) << ',' << v_bias::sup(iv[i]) << ']';
	}

	out << std::endl << "}" << std::endl << std::endl;
	out.flush();
}

END_NAMESPACE_ELISA

#endif // HYBRID_UTIL_H
